package com.power.sifa.correction.model.pojo.bo.rule;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.power.sifa.correction.model.Cre_record_ga;
import com.power.sifa.correction.model.Crw_rule_disabled;
import com.power.sifa.correction.model.Crw_rule_samecase;
import com.power.sifa.correction.model.pojo.bo.CheckRuleRequestBO;
import com.power.sifa.correction.model.pojo.bo.CheckRuleResultBO;
import com.power.sifa.correction.model.pojo.bo.SameCasePersonBO;
import com.power.sifa.util.GeoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName SameCaseGatherRule
 * @Author xiongzw
 * @Date 2023/12/10 9:58
 * @Description 同案犯聚集规则
 * @Version: 1.0
 **/

@Slf4j
public class SameCaseGatherRuleHandler extends AbstractRuleHandler {

    /**
     * 同案犯聚集规则校验方法
     *
     * @param request
     * @param checkRuleResultList
     */
    @Override
    public void handleRule(CheckRuleRequestBO request, List<CheckRuleResultBO> checkRuleResultList) {
        log.info("-------同案犯聚集规则校验中-------");

        if (Objects.nonNull(this.getNextRule())) {
            this.getNextRule().handleRule(request, checkRuleResultList);
        }
        // 进行规则校验
        // 查询当前的聚集规则
        List<Crw_rule_samecase> samecaseRules = request.getSameCaseRules();
        log.info(" -------当前请求的同案犯规则数量 {} ------- ", samecaseRules.size());
        Boolean isSameCaseResult = Boolean.FALSE;
        if (ObjectUtil.isNull(request.getLatcamera()) || ObjectUtil.isNull(request.getLngcamera())) {
            log.info(" -------当前公安数据拍摄经纬度为空，无需校验 -------", request.getPerid());
        } else {
            // 拍摄纬度
            Double latCamera = request.getLatcamera().doubleValue();
            // 拍摄经度
            Double lngCamera = request.getLngcamera().doubleValue();
            if (CollectionUtil.isNotEmpty(samecaseRules) && CollectionUtil.isNotEmpty(request.getSameCasePersonList())) {
                List<SameCasePersonBO> sameCasePersonList = request.getSameCasePersonList();
                List<String> descibeList = new ArrayList<>();
                for (Crw_rule_samecase samecaseRule : samecaseRules) {
                    try {
                        // 屏蔽规则和屏蔽人员
                        List<Crw_rule_disabled> disabledRules = request.getDisabledRules();
                        Set<String> disabledPersonSet = new HashSet<>();
                        if (CollectionUtil.isNotEmpty(disabledRules)) {
                            List<Crw_rule_disabled> singeRuleDisabledList = disabledRules.stream().filter(el -> el.getRuleid().equals(samecaseRule.getId())).collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(singeRuleDisabledList)) {
                                singeRuleDisabledList.stream().forEach(el -> {
                                    if (StringUtils.isNotEmpty(el.getDisabledperid())) {
                                        disabledPersonSet.add(el.getDisabledperid());
                                    }
                                });
                            }
                        }
                        String sameCaseRuleId = samecaseRule.getId();
                        // 范围： 米
                        Integer rangeSpace = samecaseRule.getRange_space();
                        if (ObjectUtil.isNotNull(rangeSpace)) {
                            // 查询当前规则涉及的同案犯数据,并且排除当前自己的数据
                            List<SameCasePersonBO> filterPersonList = sameCasePersonList.stream().filter(element -> element.getRuleId().equals(sameCaseRuleId)).filter(el -> !el.getPerId().equals(request.getPerid()))
                                    .collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(filterPersonList)) {
                                // 计算当前时间范围内的全部数据的距离，
                                for (SameCasePersonBO sameCasePerson : filterPersonList) {
                                    isSameCaseResult = Boolean.FALSE;
                                    descibeList = new ArrayList<>();
                                    List<Cre_record_ga> record_gas_persons = sameCasePerson.getRe_record_gas();
                                    if (CollectionUtil.isEmpty(record_gas_persons)) {
                                        log.info(" ------- 当前聚集设置人员:{}没有对应公安数据，无需校验 -------", sameCasePerson.getPerId());
                                        continue;
                                    }
                                    if (ObjectUtil.isNull(sameCasePerson.getPersonInfo())) {
                                        log.info(" ------- 当前聚集设置人员:校验的人员未保存社矫数据，无法校验-------", sameCasePerson.getPerId());
                                        continue;
                                    }
                                    // 判断人员是否是屏蔽人员
                                    if (CollectionUtil.isNotEmpty(disabledPersonSet) && disabledPersonSet.contains(sameCasePerson.getPerId())) {
                                        log.info("-------社矫人员{}设置了屏蔽聚集规则{}，屏蔽人员id{}，该条规则校验跳过-------", request.getPersonInfo().getName(), samecaseRule.getId(), sameCasePerson.getPersonInfo().getName());
                                        continue;
                                    }
                                    // 计算当前的坐标距离
                                    for (Cre_record_ga cre_record_ga : record_gas_persons) {
                                        // 计算当前的坐标距离
                                        if (ObjectUtil.isNull(cre_record_ga.getLatcamera()) || ObjectUtil.isNull(cre_record_ga.getLngcamera())) {
                                            continue;
                                        }
                                        Double latCameraEndposition = cre_record_ga.getLatcamera().doubleValue();
                                        Double lngCameraEndposition = cre_record_ga.getLngcamera().doubleValue();
                                        log.info(" ------ 计算起点坐标： {} {} -------", lngCamera, latCamera);
                                        log.info(" ------ 计算终点坐标： {} {} -------", lngCameraEndposition,
                                                latCameraEndposition);
                                        Integer distanceBetween = GeoUtil.computeDistanceBetween(lngCamera, latCamera,
                                                lngCameraEndposition, latCameraEndposition).intValue();
                                        log.info(" ------ 计算的相距距离： {} -------", distanceBetween);
                                        if (distanceBetween.compareTo(rangeSpace) < 0) {
                                            isSameCaseResult = Boolean.TRUE;
                                            StringBuffer describeBuff = new StringBuffer();
                                            SimpleDateFormat fmt = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
                                            String timeStr = ObjectUtil.isNotEmpty(cre_record_ga.getRectime()) ? fmt.format(cre_record_ga.getRectime()) : "";
                                            describeBuff.append("社矫人员：").append(request.getPersonInfo().getName()).append("与社矫人员：")
                                                    .append(sameCasePerson.getPersonInfo().getName()).append("于").append(timeStr)
                                                    .append("在地点：").append(cre_record_ga.getAddr()).append("，发生聚集，距离：").append(distanceBetween).append("米，").append("违反人群聚集规则：").append(samecaseRule.getName());
                                            descibeList.add(describeBuff.toString());
                                            break;
                                        }
                                    }
                                    if (isSameCaseResult) {
                                        log.info("当前人员{}违法同案犯聚集规则{}", request.getPersonInfo().getName(), samecaseRule.getId());
                                        CheckRuleResultBO checkRuleResult = CheckRuleResultBO.builder().validate(isSameCaseResult).ruleId(samecaseRule.getId()).rectime(request.getRectime()).gaid(request.getId())
                                                .ruleName(samecaseRule.getName()).describeList(descibeList)
                                                .latcamera(request.getLatcamera()).lngcamera(request.getLngcamera()).build();
                                        checkRuleResultList.add(checkRuleResult);
                                    } else {
                                        log.info("当前人员{}未违反同案犯聚集规则", request.getPersonInfo().getName());
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("-------同案犯聚集规则校验异常-------");
                        e.printStackTrace();
                    }
                }
            } else {
                log.info("-------同案犯聚集规则数量为零或未设置聚集人群: 无需校验结束-------");
            }
        }
    }
}
